﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections;

namespace ETenki
{
    public partial class FormDistill : Form
    {
        private int progress = 0;
        private int status = 0; // 0: 集計待ち, 1: 集計中
        private int wordCount = 0;
        private int[] urlCount = new int[11];
        private List<List<string[]>> items = new List<List<string[]>>();
        private Hashtable dirItems = new Hashtable();
        private string baseDir;
        private int searchDirDepth = 0;
        private ListViewColumnSorter sorter;
        private int rank = 0;

        public FormDistill()
        {
            InitializeComponent();
            sorter = new ListViewColumnSorter();
        }
        
        private void showFilesInfo()
        {
            wordCount = 0;
            for (int i = 0; i < urlCount.Length; i++)
			{
                urlCount[i] = 0;
			}
            
            // ファイル情報の表示
            foreach (string path in listBox1.Items)
            {
                FileStream stream = new FileStream(path, FileMode.Open);
                StreamReader reader = new StreamReader(stream);
                string line;

                while ((line = reader.ReadLine()) != null)
                {
                    wordCount++;
                    int n = line.Split().Length;
                    for (int i = 1; i < n; i++)
                    {
                        urlCount[i]++;
                    }
                }
                reader.Close();
                stream.Close();
            }
            for (int i = 0; i < urlCount.Length; i++)
            {
                urlCount[0] += urlCount[i];
            }
            textBox1.Text = "ファイル数: " + listBox1.Items.Count + "\r\n";
            textBox1.Text = textBox1.Text + "単語の総数: " + wordCount.ToString() + "\r\n";
            textBox1.Text = textBox1.Text + "URLの総数: " + urlCount[0].ToString() + "\r\n";
            if (wordCount == 0)
            {
                button3.Enabled = false;
            }
            else
            {
                button3.Enabled = true;
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (items.Count > 0 && MessageBox.Show("集計結果がクリアされますがよろしいですか?", "INFORMATION", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
            {
                return;
            }
            
            // ファイル追加
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Multiselect = true;
            dialog.InitialDirectory = ".";
            dialog.Filter = "検索結果ファイル(*.txt)|*.txt|すべてのファイル(*.*)|*.*";
            dialog.FilterIndex = 0;
            dialog.CheckFileExists = true;
            dialog.CheckPathExists = true;
            if (dialog.ShowDialog() != DialogResult.Cancel)
            {
                listBox1.Items.AddRange(dialog.FileNames);
                showFilesInfo();
                items.Clear();
                dirItems.Clear();
                listView1.Items.Clear();
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (items.Count > 0 && MessageBox.Show("集計結果がクリアされますがよろしいですか?", "INFORMATION", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
            {
                return;
            }
            
            // ファイル削除
            foreach (int i in listBox1.SelectedIndices)
            {
                listBox1.Items.RemoveAt(i);
            }
            showFilesInfo();
            items.Clear();
            dirItems.Clear();
            listView1.Items.Clear();
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (status == 0)
            {
                // 集計開始(キャッシュ)
                button1.Enabled = false;
                button2.Enabled = false;
                listBox1.Enabled = false;
                textBox1.Enabled = false;
                groupBox1.Enabled = false;
                menuStrip1.Enabled = false;
                button3.Text = "キャンセル";
                listView1.Enabled = false;
                button4.Enabled = false;
                button5.Enabled = false;
                textBox2.Enabled = false;
                textBox3.Enabled = false;
                button6.Enabled = false;
                status = 1;
                progress = 0;
                int r = int.Parse(comboBox1.Text);
                if (radioButton2.Checked && r >= 1 && r <= 10)
                {
                    rank = r;
                }
                else
                {
                    rank = 0;
                }
                if (items.Count == 0)
                {
                    for (int i = 0; i <= 10; i++)
                    {
                        items.Add(new List<string[]>());
                    }
                }
                toolStripProgressBar1.Minimum = 0;
                toolStripProgressBar1.Maximum = wordCount;
                toolStripProgressBar1.Value = 0;
                toolStripStatusLabel1.Text = "集計を開始します...";
                backgroundWorker1.RunWorkerAsync();
                timer1.Enabled = true;
            }
            else
            {
                // キャンセル
                button3.Enabled = false;
                toolStripStatusLabel1.Text = "キャンセルしています...";
                backgroundWorker1.CancelAsync();
            }
        }

        private void radioButton2_CheckedChanged(object sender, EventArgs e)
        {
            comboBox1.Enabled = radioButton2.Checked;
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
        }

        private void listBox1_SelectedValueChanged(object sender, EventArgs e)
        {
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listBox1.SelectedItems.Count == 0)
            {
                button2.Enabled = false;
            }
            else
            {
                button2.Enabled = true;
            }
        }
        
        private void button5_Click(object sender, EventArgs e)
        {
            // ドメイン解析
            if (status == 0)
            {
                // 集計ファイルがないなら中止
                bool fFlag=true;
                foreach (string path in listBox1.Items)
                {
                    if (!File.Exists(path))
                    {
                        fFlag = false;
                        break;
                    }
                }
                if (!fFlag)
                {
                    MessageBox.Show("集計ファイルが見つかりません。");
                    return;
                }
                // 集計開始
                if (rank >= 1 && MessageBox.Show("ドメインの解析機能は特定順位の集計に対応していません。上位10件すべてのURLに対して行います。\r\n現在リストに表示されているリストは特定順位に関するドメインの集計結果ですが、このまま続行しますか？", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
                {
                    return;
                }
                string localBase = listView1.SelectedItems[0].Text;
                if (OptionNonConfirmAnlyToolStripMenuItem.Checked == false && dirItems.Contains(localBase) == false && MessageBox.Show("選択したURLを解析するために、さらに集計を行います。よろしいですか？", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
                {
                    return;
                }
                    
                button1.Enabled = false;
                button2.Enabled = false;
                listBox1.Enabled = false;
                textBox1.Enabled = false;
                groupBox1.Enabled = false;
                menuStrip1.Enabled = false;
                listView1.Enabled = false;
                button4.Enabled = false;
                button5.Text = "キャンセル";
                status = 2;
                progress = 0;
                baseDir = localBase;
                searchDirDepth = getURLDepth(localBase) + 1;
                if (dirItems.Contains(baseDir) == false)
                {
                    List<string[]> dirItem = new List<string[]>();
                    dirItems[baseDir] = dirItem;
                }
                toolStripProgressBar1.Minimum = 0;
                toolStripProgressBar1.Maximum = wordCount;
                toolStripProgressBar1.Value = 0;
                toolStripStatusLabel1.Text = "集計を開始します...";
                backgroundWorker2.RunWorkerAsync();
                timer1.Enabled = true;
            }
            else
            {
                // キャンセル
                button5.Enabled = false;
                toolStripStatusLabel1.Text = "キャンセルしています...";
                backgroundWorker2.CancelAsync();
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (status == 1)
            {
                backgroundWorker1.ReportProgress(progress);
            }
            else if (status == 2)
            {
                backgroundWorker2.ReportProgress(progress);
            }
        }

        private int getURLDepth(string url)
        {
            int depth = 0;
            int i = 7;

            while ((i = url.IndexOf("/", i + 1)) > 0)
            {
                depth++;
            }
            if (url.EndsWith("/"))
            {
                depth--;
            }
            
            return depth;
        }

        private string getSubURL(string url, int depth)
        {
            int len = 7;
            for (int i = 0; i <= depth; i++)
			{
                len = url.IndexOf("/", len + 1);
                if (len == -1)
                {
                    len = url.Length;
                    break;
                }
			}

            string suburl = url.Substring(0, len);
            if (suburl.EndsWith("/"))
            {
                suburl = url.Substring(0, len - 1);
            }
            return suburl;
        }
        
        private bool isEqualURL(string url1, string url2, int depth)
        {
            // depth==0の場合、ドメインが同じかどうかの比較
            // depth==Nの場合、N階層目まで同じURLかどうかの比較
            string suburl1 = getSubURL(url1, depth);
            string suburl2 = getSubURL(url2, depth);
            bool eq =  url1.Equals(url2);

            return eq;
        }

        private void addURL(List<string[]> list, string url, int depth)
        {
            // ListViewにURL1個を追加
            string suburl = getSubURL(url, depth);

            foreach (string[] item in list)
            {
                if (item[0].Equals(suburl))
                {
                    item[1] = (int.Parse(item[1]) + 1).ToString();
                    return;
                }
            }
            string[] newitem = { suburl, "1" };
            list.Add(newitem);
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            // 集計
            if (items[rank].Count == 0)
            {
                foreach (string path in listBox1.Items)
                {
                    FileStream stream = new FileStream(path, FileMode.Open);
                    StreamReader reader = new StreamReader(stream);
                    try
                    {
                        string line;
                        while ((line = reader.ReadLine()) != null && !backgroundWorker1.CancellationPending)
                        {
                            string[] urls = line.Split('\t');
                            if (rank < 1)
                            {
                                for (int i = 1; i < urls.Length; i++)
                                {
                                    addURL(items[rank], urls[i], 0);
                                }
                            }
                            else if (urls.Length > rank)
                            {
                                addURL(items[rank], urls[rank], 0);
                            }
                            progress++;
                        }
                    }
                    finally
                    {
                        reader.Close();
                        stream.Close();
                    }
                    if (backgroundWorker1.CancellationPending)
                    {
                        e.Cancel = true;
                        break;
                    }
                }
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            toolStripProgressBar1.Value = progress;
            toolStripStatusLabel1.Text = "集計中(" + progress + "/" + wordCount + ")";
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            status = 0;
            button1.Enabled = true;
            button3.Enabled = true;
            button3.Text = "集計";
            listBox1.Enabled = true;
            textBox1.Enabled = true;
            groupBox1.Enabled = true;
            timer1.Enabled = false;
            menuStrip1.Enabled = true;
            textBox2.Enabled = true;
            textBox3.Enabled = true;
            button6.Enabled = true;

            if (e.Cancelled == false)
            {
                toolStripStatusLabel1.Text = "リストを更新しています...";

                listView1.Visible = false;
                listView1.ListViewItemSorter = null;
                listView1.Items.Clear();
                for (int i = 0; i < items[rank].Count; i++)
                {
                    listView1.Items.Add(new ListViewItem(items[rank][i]));
                }
                listView1.Visible = true;
                listView1.Enabled = true;

                toolStripProgressBar1.Value = toolStripProgressBar1.Maximum;
                toolStripStatusLabel1.Text = "完了しました。";

                if (rank < 1)
                {
                    textBox1.Text = textBox1.Text + "---- 全順位での集計結果 ----\r\n";
                }
                else
                {
                    textBox1.Text = textBox1.Text + "---- " + rank + "位での集計結果 ----\r\n";
                }
                textBox1.Text = textBox1.Text + "集計した単語の総数: " + wordCount + "\r\n";
                textBox1.Text = textBox1.Text + "集計したURLの総数: " + urlCount[rank].ToString() + "\r\n";
                textBox1.Text = textBox1.Text + "集計結果のURL件数: " + items[rank].Count + "\r\n";
                textBox2.Text = "1";
                textBox3.Text = listView1.Items.Count.ToString();
            }
            else
            {
                items[rank].Clear();
                toolStripProgressBar1.Value = toolStripProgressBar1.Minimum;
                toolStripStatusLabel1.Text = "キャンセルされました。";
            }
        }

        private void toolStripStatusLabel1_Click(object sender, EventArgs e)
        {

        }

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
        }

        private void listView1_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            if (e.Column == sorter.SortColumn)
            {
                if (sorter.Order == SortOrder.Descending)
                {
                    sorter.Order = SortOrder.Ascending;
                }
                else
                {
                    sorter.Order = SortOrder.Descending;
                }
            }
            else
            {
                if (listView1.ListViewItemSorter != sorter)
                {
                    listView1.ListViewItemSorter = sorter;
                }
                sorter.SortColumn = e.Column;
                sorter.Order = SortOrder.Descending;
            }
            listView1.Sort();
        }

        private void toolStripMenuItem2_Click(object sender, EventArgs e)
        {

        }

        private void ExportToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }

        private bool loadFile(string path)
        {
            bool success = false;
            FileStream stream = new FileStream(path, FileMode.Open);
            StreamReader reader = new StreamReader(stream);
            string line;

            try
            {
                // file list
                listBox1.Items.Clear();
                line = reader.ReadLine();
                if (line.Equals("<FileList>"))
                {
                    while ((line = reader.ReadLine()) != "</FileList>")
                    {
                        listBox1.Items.Add(line);
                    }
                }
                else
                {
                    throw new Exception("FileListノードがありません。");
                }

                // text info
                textBox1.Text = "";
                line = reader.ReadLine();
                if (line.Equals("<WordCount>"))
                {
                    line = reader.ReadLine();
                    wordCount = int.Parse(line);
                    line = reader.ReadLine();
                }
                else
                {
                    throw new Exception("WordCountノードがありません。");
                }

                // text info
                textBox1.Text = "";
                line = reader.ReadLine();
                if (line.Equals("<TextInfo>"))
                {
                    while ((line = reader.ReadLine()) != "</TextInfo>")
                    {
                        textBox1.Text = textBox1.Text + line + "\r\n";
                    }
                }
                else
                {
                    throw new Exception("TextInfoノードがありません。");
                }

                // Counting Result
                listView1.Items.Clear();
                items.Clear();
                for (int i = 0; i <= 10; i++)
                {
                    items.Add(new List<string[]>());
                }
                line = reader.ReadLine();
                if (line.Equals("<CountingResult>"))
                {
                    while ((line = reader.ReadLine()) != "</CountingResult>")
                    {
                        if (line.Equals("<ALL>"))
                        {
                            while ((line = reader.ReadLine()) != "</ALL>")
                            {
                                string[] urlline = line.Split(',');
                                items[0].Add(urlline);
                            }
                        }
                        else
                        {
                            throw new Exception("ALLノードがありません");
                        }

                        for (int i = 1; i <= 10; i++)
                        {
                            line = reader.ReadLine();
                            if (line.Equals("<RANK" + i.ToString() + ">"))
                            {
                                while ((line = reader.ReadLine()) != "</RANK" + i.ToString() + ">")
                                {
                                    string[] urlline = line.Split(',');
                                    items[i].Add(urlline);
                                }
                            }
                            else
                            {
                                throw new Exception("RANK" + i.ToString() + "ノードがありません");
                            }
                        }
                    }
                }
                else
                {
                    throw new Exception("CountingResultノードがありません。");
                }

                // directory result
                dirItems.Clear();
                while ((line = reader.ReadLine()) != null && line.Equals("<DirectoryResult>"))
                {
                    // base directory
                    if (reader.ReadLine().Equals("<BaseDirectory>") == false)
                    {
                        throw new Exception("BaseDirectoryは必須です。");
                    }
                    List<string[]> dirItem = new List<string[]>();
                    line = reader.ReadLine();
                    dirItems[line] = dirItem;
                    if (reader.ReadLine().Equals("</BaseDirectory>") == false)
                    {
                        throw new Exception("BaseDirectoryが閉じていません。");
                    }
                    // child directory
                    if (reader.ReadLine().Equals("<ChildDirectory>") == false)
                    {
                        throw new Exception("ChildDirectoryは必須です。");
                    }
                    while ((line = reader.ReadLine()) != "</ChildDirectory>")
                    {
                        string[] urlline = line.Split(',');
                        dirItem.Add(urlline);
                    }
                    if (reader.ReadLine().Equals("</DirectoryResult>") == false)
                    {
                        throw new Exception("DirectoryResultが閉じていません。");
                    }
                }

                success = true;
            }
            catch
            {
                success = false;
            }
            finally
            {
                reader.Close();
                stream.Close();
            }
            
            return success;
        }

        private void LoadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 読み込み
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Multiselect = true;
            dialog.InitialDirectory = ".";
            dialog.Filter = "集計ファイル(*.etk)|*.etk|すべてのファイル(*.*)|*.*";
            dialog.FilterIndex = 0;
            dialog.CheckFileExists = true;
            dialog.CheckPathExists = true;
            if (dialog.ShowDialog() != DialogResult.Cancel)
            {
                toolStripStatusLabel1.Text = "読み込んでいます...";
                if (loadFile(dialog.FileName))
                {
                    toolStripStatusLabel1.Text = "読み込みました: " + dialog.FileName;
                    button3.Enabled = true;
                }
                else
                {
                    toolStripStatusLabel1.Text = "読み込みに失敗しました";
                }
            }
        }

        private bool saveFile(string path)
        {
            bool success = false;
            FileStream stream = new FileStream(path, FileMode.Create);
            StreamWriter writer = new StreamWriter(stream);
            try
            {
                // file list
                writer.WriteLine("<FileList>");
                foreach (string item in listBox1.Items)
                {
                    writer.WriteLine(item);
                }
                writer.WriteLine("</FileList>");

                // word count
                writer.WriteLine("<WordCount>");
                writer.WriteLine(wordCount.ToString());
                writer.WriteLine("</WordCount>");

                // text info
                writer.WriteLine("<TextInfo>");
                writer.Write(textBox1.Text);
                writer.WriteLine("</TextInfo>");

                // shukei list
                if (items.Count == 0)
                {
                    writer.WriteLine("<CountingResult>");
                    writer.WriteLine("<ALL>");
                    writer.WriteLine("</ALL>");

                    for (int i = 1; i <= 10; i++)
                    {
                        writer.WriteLine("<RANK" + i.ToString() + ">");
                        writer.WriteLine("</RANK" + i.ToString() + ">");
                    }
                    writer.WriteLine("</CountingResult>");
                }
                else
                {
                    writer.WriteLine("<CountingResult>");
                    writer.WriteLine("<ALL>");
                    foreach (string[] item in items[0])
                    {
                        writer.WriteLine(item[0] + "," + item[1]);
                    }
                    writer.WriteLine("</ALL>");

                    for (int i = 1; i <= 10; i++)
                    {
                        writer.WriteLine("<RANK" + i.ToString() + ">");
                        foreach (string[] item in items[i])
                        {
                            writer.WriteLine(item[0] + "," + item[1]);
                        }
                        writer.WriteLine("</RANK" + i.ToString() + ">");
                    }
                    writer.WriteLine("</CountingResult>");
                }

                // directory result
                if (dirItems.Count > 0)
                {
                    foreach (DictionaryEntry entry in dirItems)
                    {
                        writer.WriteLine("<DirectoryResult>");
                        // base directory
                        writer.WriteLine("<BaseDirectory>");
                        writer.WriteLine((string)entry.Key);
                        writer.WriteLine("</BaseDirectory>");
                        
                        // child directory
                        writer.WriteLine("<ChildDirectory>");
                        List<string[]> dirItem = (List<string[]>)entry.Value;
                        foreach (string[] item in dirItem)
                        {
                            writer.WriteLine(item[0] + "," + item[1]);
                        }
                        writer.WriteLine("</ChildDirectory>");
                        writer.WriteLine("</DirectoryResult>");
                    }
                }
                success = true;
            }
            catch
            {
                success = false;
            }
            finally
            {
                writer.Close();
                stream.Close();
            }

            return success;
        }

        private void SaveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 保存
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.InitialDirectory = ".";
            dialog.Filter = "集計ファイル(*.etk)|*.etk|すべてのファイル(*.*)|*.*";
            dialog.FilterIndex = 0;
            dialog.AddExtension = true;
            dialog.OverwritePrompt = true;

            if (dialog.ShowDialog() != DialogResult.Cancel)
            {
                toolStripStatusLabel1.Text = "保存しています...";
                if (saveFile(dialog.FileName))
                {
                    toolStripStatusLabel1.Text = "保存しました: " + dialog.FileName;
                }
                else
                {
                    toolStripStatusLabel1.Text = "保存に失敗しました";
                }
            }
        }

        private void QuitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 終了
            this.Close();
        }

        private void listView1_DoubleClick(object sender, EventArgs e)
        {
            // URLを開く
            System.Diagnostics.Process.Start(listView1.SelectedItems[0].Text);
        }

        private void button4_Click(object sender, EventArgs e)
        {
            // 一つうえのディレクトリ
            if (status == 0)
            {
                // 集計開始
                if (rank >= 1 && MessageBox.Show("ドメインの解析機能は特定順位の集計に対応していません。上位10件すべてのURLに対して行います。\r\n現在表示されているリストは特定順位に関するドメインの集計結果ですが、このまま続行しますか？", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
                {
                    return;
                }
                int localDepth = getURLDepth(baseDir) - 1;
                if (localDepth < 0)
                {
                    // 全URLの集計と同様の動作
                    radioButton1.Checked = true;
                    button3.PerformClick();
                    return;
                }
                string localBase = getSubURL(baseDir, localDepth);
                if (OptionNonConfirmAnlyToolStripMenuItem.Checked == false && dirItems.Contains(localBase) == false && MessageBox.Show("上のディレクトリに戻るために、さらに集計を行います。よろしいですか？", "", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
                {
                    return;
                }
                button1.Enabled = false;
                button2.Enabled = false;
                listBox1.Enabled = false;
                textBox1.Enabled = false;
                groupBox1.Enabled = false;
                menuStrip1.Enabled = false;
                listView1.Enabled = false;
                button5.Enabled = false;
                button4.Text = "キャンセル";
                status = 2;
                progress = 0;
                baseDir = localBase;
                searchDirDepth = localDepth + 1;
                if (dirItems.Contains(baseDir) == false)
                {
                    List<string[]> dirItem = new List<string[]>();
                    dirItems[baseDir] = dirItem;
                }
                toolStripProgressBar1.Minimum = 0;
                toolStripProgressBar1.Maximum = wordCount;
                toolStripProgressBar1.Value = 0;
                toolStripStatusLabel1.Text = "集計を開始します...";
                backgroundWorker2.RunWorkerAsync();
                timer1.Enabled = true;
            }
            else
            {
                // キャンセル
                button5.Enabled = false;
                toolStripStatusLabel1.Text = "キャンセルしています...";
                backgroundWorker2.CancelAsync();
            }
        }

        private void listView1_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            if (listView1.SelectedItems.Count == 0)
            {
                button5.Enabled = false;
            }
            else
            {
                button5.Enabled = true;
            }
        }

        private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
        {
            // ドメイン解析
            List<string[]> dirItem = (List<string[]>)dirItems[baseDir];
            if (dirItem.Count == 0)
            {
                foreach (string path in listBox1.Items)
                {
                    FileStream stream = new FileStream(path, FileMode.Open);
                    StreamReader reader = new StreamReader(stream);
                    try
                    {
                        string line;
                        while ((line = reader.ReadLine()) != null && !backgroundWorker2.CancellationPending)
                        {
                            string[] urls = line.Split('\t');
                            for (int i = 1; i < urls.Length; i++)
                            {
                                if (urls[i].StartsWith(baseDir) || baseDir.StartsWith(urls[i]))
                                {
                                    addURL(dirItem, urls[i], searchDirDepth);
                                }
                            }
                            progress++;
                        }
                    }
                    finally
                    {
                        reader.Close();
                        stream.Close();
                    }
                    if (backgroundWorker2.CancellationPending)
                    {
                        e.Cancel = true;
                        break;
                    }
                }
            }
        }

        private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            toolStripProgressBar1.Value = progress;
            toolStripStatusLabel1.Text = "集計中(" + progress + "/" + wordCount + ")";
        }

        private void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // ドメイン解析終了
            status = 0;
            button1.Enabled = true;
            button3.Enabled = true;
            listBox1.Enabled = true;
            textBox1.Enabled = true;
            groupBox1.Enabled = true;
            timer1.Enabled = false;
            menuStrip1.Enabled = true;
            if (searchDirDepth>0)
            {
                button4.Enabled = true;
            }
            else
            {
                button4.Enabled = false;
            }
            button4.Text = "1つ上のディレクトリへ";
            button5.Enabled = false;
            button5.Text = "選択したドメインをさらに解析";

            if (e.Cancelled == false)
            {
                toolStripStatusLabel1.Text = "リストを更新しています...";

                listView1.Visible = false;
                listView1.ListViewItemSorter = null;
                listView1.Items.Clear();
                rank = 0;
                List<string[]> dirItem = (List<string[]>)dirItems[baseDir];
                for (int i = 0; i < dirItem.Count; i++)
                {
                    listView1.Items.Add(new ListViewItem(dirItem[i]));
                }
                listView1.Visible = true;
                listView1.Enabled = true;

                toolStripProgressBar1.Value = toolStripProgressBar1.Maximum;
                toolStripStatusLabel1.Text = "完了しました。";
                
                textBox1.Text = textBox1.Text + "---- ディレクトリ解析結果 ----\r\n";
                textBox1.Text = textBox1.Text + "基本のURL: " + baseDir + "\r\n";
                textBox1.Text = textBox1.Text + "探索した深さ: " + searchDirDepth + "階層\r\n";
                textBox1.Text = textBox1.Text + "集計結果のURL件数: " + dirItem.Count + "件\r\n";
            }
            else
            {
                dirItems.Remove(baseDir);
                toolStripProgressBar1.Value = toolStripProgressBar1.Minimum;
                toolStripStatusLabel1.Text = "キャンセルされました。";
            }
        }

        private void FormDistill_Load(object sender, EventArgs e)
        {

        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void button6_Click(object sender, EventArgs e)
        {
            int stt = int.Parse(textBox2.Text), end = int.Parse(textBox3.Text);
            
            // 書き出し
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.InitialDirectory = ".";
            dialog.Filter = "カンマ区切りファイル(*.csv)|*.csv|すべてのファイル(*.*)|*.*";
            dialog.FilterIndex = 0;
            dialog.AddExtension = true;
            dialog.OverwritePrompt = true;

            if (dialog.ShowDialog() != DialogResult.Cancel)
            {
                FileStream stream = new FileStream(dialog.FileName, FileMode.Create);
                StreamWriter writer = new StreamWriter(stream);
                try
                {
                    toolStripStatusLabel1.Text = "書き出しています...";
                    for (int i = stt - 1; i <= end - 1; i++)
                    {
                        ListViewItem item = listView1.Items[i];
                        writer.WriteLine(item.Text + "," + item.SubItems[1].Text);
                    }
                    toolStripStatusLabel1.Text = "書き出しました: " + dialog.FileName;
                }
                finally
                {
                    writer.Close();
                    stream.Close();
                }
            }
        }

        private void OptionNonConfirmAnlyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OptionNonConfirmAnlyToolStripMenuItem.Checked = !OptionNonConfirmAnlyToolStripMenuItem.Checked;
        }
    }
    /// <summary>
    /// This class is an implementation of the 'IComparer' interface.
    /// </summary>
    public class ListViewColumnSorter : IComparer
    {
        /// <summary>
        /// Specifies the column to be sorted
        /// </summary>
        private int ColumnToSort;
        /// <summary>
        /// Specifies the order in which to sort (i.e. 'Ascending').
        /// </summary>
        private SortOrder OrderOfSort;
        /// <summary>
        /// Case insensitive comparer object
        /// </summary>
        private CaseInsensitiveComparer ObjectCompare;

        /// <summary>
        /// Class constructor.  Initializes various elements
        /// </summary>
        public ListViewColumnSorter()
        {
            // Initialize the column to '0'
            ColumnToSort = 0;

            // Initialize the sort order to 'none'
            OrderOfSort = SortOrder.None;

            // Initialize the CaseInsensitiveComparer object
            ObjectCompare = new CaseInsensitiveComparer();
        }

        /// <summary>
        /// This method is inherited from the IComparer interface.  It compares the two objects passed using a case insensitive comparison.
        /// </summary>
        /// <param name="x">First object to be compared</param>
        /// <param name="y">Second object to be compared</param>
        /// <returns>The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y'</returns>
        public int Compare(object x, object y)
        {
            int compareResult;
            ListViewItem listviewX, listviewY;

            // Cast the objects to be compared to ListViewItem objects
            listviewX = (ListViewItem)x;
            listviewY = (ListViewItem)y;

            // Compare the two items
            if (ColumnToSort == 1)
            {
                compareResult = ObjectCompare.Compare(int.Parse(listviewX.SubItems[ColumnToSort].Text), int.Parse(listviewY.SubItems[ColumnToSort].Text));
            }
            else
            {
                compareResult = ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text, listviewY.SubItems[ColumnToSort].Text);
            }

            // Calculate correct return value based on object comparison
            if (OrderOfSort == SortOrder.Ascending)
            {
                // Ascending sort is selected, return normal result of compare operation
                return compareResult;
            }
            else if (OrderOfSort == SortOrder.Descending)
            {
                // Descending sort is selected, return negative result of compare operation
                return (-compareResult);
            }
            else
            {
                // Return '0' to indicate they are equal
                return 0;
            }
        }

        /// <summary>
        /// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0').
        /// </summary>
        public int SortColumn
        {
            set
            {
                ColumnToSort = value;
            }
            get
            {
                return ColumnToSort;
            }
        }

        /// <summary>
        /// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending').
        /// </summary>
        public SortOrder Order
        {
            set
            {
                OrderOfSort = value;
            }
            get
            {
                return OrderOfSort;
            }
        }

    }

}
